package com.recipedb.sprint.service.impl;

import com.recipedb.sprint.entity.PointsRewards;
import com.recipedb.sprint.entity.PointRecords;
import com.recipedb.sprint.repository.PointsRewardsRepository;
import com.recipedb.sprint.repository.PointRecordsRepository;
import com.recipedb.sprint.service.PointsRewardsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.recipedb.sprint.entity.Users;
import com.recipedb.sprint.repository.UsersRepository;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class PointsRewardsServiceImpl implements PointsRewardsService {

    private final PointsRewardsRepository pointsRewardsRepository;
    private final PointRecordsRepository pointRecordsRepository;

    // 注入 UsersRepository 用于查询用户
    private final UsersRepository usersRepository;

    public PointsRewardsServiceImpl(PointsRewardsRepository pointsRewardsRepository,
                                    PointRecordsRepository pointRecordsRepository,
                                    UsersRepository usersRepository) {
        this.pointsRewardsRepository = pointsRewardsRepository;
        this.pointRecordsRepository = pointRecordsRepository;

        this.usersRepository = usersRepository;
    }

    @Override
    public Long getUserIdByUsername(String username) {
        return usersRepository.findByUsername(username)
                .map(Users::getUserid) // 从 Users 实体中获取 userid
                .orElseThrow(() -> new RuntimeException("用户不存在：" + username));
    }


    @Override
    public Map<String, Object> getPointsBalance(Long userid) {
        PointsRewards pointsRewards = pointsRewardsRepository.findByUserid(userid)
                .orElseGet(() -> pointsRewardsRepository.save(new PointsRewards(userid)));

        Map<String, Object> result = new HashMap<>();
        result.put("userid", userid);
        result.put("points", pointsRewards.getPoints());
        result.put("updatedAt", pointsRewards.getUpdatedAt());
        return result;
    }

    @Override
    public List<Map<String, Object>> getPointsHistory(Long userid) {
        List<PointRecords> records = pointRecordsRepository.findByUseridOrderByCreatedAtDesc(userid);

        return records.stream().map(record -> {
            Map<String, Object> history = new HashMap<>();
            history.put("recordId", record.getRecordId());
            history.put("pointsChange", record.getPointsChange());
            history.put("sourceType", record.getSourceType());
            history.put("description", record.getDescription());
            history.put("relatedId", record.getRelatedId());
            history.put("createdAt", record.getCreatedAt());
            return history;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void awardDailyLoginPoints(Long userid) {
        Long todayCount = pointRecordsRepository.countTodayRecordsByType(userid, "DAILY_LOGIN");
        if (todayCount > 0) {
            throw new RuntimeException("今日已领取登录积分");
        }
        awardPoints(userid, 10, "DAILY_LOGIN", "每日登录奖励", null);
    }

    @Override
    @Transactional
    public void awardConsultationPoints(Long userid, Long sessionId) {
        Long todayCount = pointRecordsRepository.countTodayRecordsByType(userid, "CONSULTATION");
        if (todayCount >= 3) {
            throw new RuntimeException("今日咨询奖励已达上限（最多3次）");
        }
        awardPoints(userid, 100, "CONSULTATION", "咨询完成奖励", sessionId);
    }

    @Override
    @Transactional
    public void awardFeedbackPoints(Long userid, Long sessionId) {
        Long todayCount = pointRecordsRepository.countTodayRecordsByType(userid, "FEEDBACK");
        if (todayCount >= 3) {
            throw new RuntimeException("今日反馈奖励已达上限（最多3次）");
        }
        awardPoints(userid, 50, "FEEDBACK", "有效反馈奖励", sessionId);
    }

    private void awardPoints(Long userid, Integer points, String sourceType, String description, Long relatedId) {
        ensureUserPointsAccountExists(userid);
        pointsRewardsRepository.addPoints(userid, points);

        // quantity 对普通积分奖励为 null
        PointRecords record = new PointRecords(userid, points, sourceType, relatedId, null, description);
        pointRecordsRepository.save(record);
    }


    private void ensureUserPointsAccountExists(Long userid) {
        if (!pointsRewardsRepository.existsByUserid(userid)) {
            pointsRewardsRepository.save(new PointsRewards(userid));
        }
    }

}
